/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MyEngine;

import Figures.*;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;

/**
 * class working in new thread wchich takes part of figures and search for best move only in those figures
 * @author Macias
 */
class Worker implements Runnable{

    int SEARCH_DEPTH;
    int INIT_NOTE;

    ABEngine eng;
    int from,to;
    boolean isWhiteMove;
//    boolean castleW,castleB,canCastleW,canCastleB;
    boolean[] castles,canCastles;
    char[][]board;
    Node root;

    int moveType;
    Point[] finalMove;
    int[] finalAddMove;

    int childNr;

    int ID;

    Neural neural;// = new Neural();
    Point[] lastMove;

    int count1;
    Worker(ABEngine aThis, int f, int t,int ThreadID,Point[] lMove) {

        eng = aThis;
        from=f;
        to=t;


        childNr=0;
        ID = ThreadID;
        lastMove=lMove;
    }



    public void run() {

        board = new char[8][8];
        neural = new Neural(isWhiteMove);
        synchronized(eng){
          SEARCH_DEPTH = eng.SEARCH_DEPTH;
          INIT_NOTE = eng.INIT_NOTE;
          isWhiteMove = eng.isWhiteMove;
          for(int c = 0;c<=7; c++)
         for(int r = 0;r<=7; r++)
                board[c][r]=eng.globalBoard[c][r];
        castles=eng.castles;
//        castleB=eng.castleB;
        }
        canCastles=castles;
//        canCastleB=castleB;
        root = new Node();
        finalMove = new Point[2];
        finalAddMove = new int[5];

        getMove();
    }
/**
 * function which is jus like getNextMove in ABEngine - it writes best move chosen from given figures,
 * it writes it in class ABEngine list
 */
    void getMove(){

          double bestNote = -INIT_NOTE;

        for(int f =from; f<to;f++){
            Figures figure;
        synchronized(eng.figures){
            figure=eng.figures.get(f);
        }

       ArrayList<Point> moves = figure.checkPossibleMoves(board);
       int [] ret = new int[8];
       switch(figure.getType()){
            case 'k':
            case 'K':ret = checkForCastle(board,isWhiteMove);
                    if(ret!=null) {
                        moves.add(new Point(ret[2],ret[3]));
                        moveType=2;
                    }

                     break;
            case 'p':
            case 'P':ret = checkForJump(root,figure,lastMove);
                             if(ret!=null) {
                                moves.add(new Point(ret[2],ret[3]));
                                moveType=3;
                                }
                             else ret= new int[8];
                    if(moves.size()>0)
                         if(moves.get(0).y==0 || moves.get(0).y==7)moveType=4;
                    break;
            default: moveType = 0;
                    ret = new int[8];
                    for(int i=0;i<=7;i++)ret[i]=0;
                        break;
            }

       for(int m=0;m<moves.size();m++){
          int[] tmp = new int[4];
          tmp[0] = figure.getPosX();
          tmp[1] = figure.getPosY();
          tmp[2] = moves.get(m).x;
          tmp[3] = moves.get(m).y;

          Node node = new Node(root,tmp);
          childNr++;
          if(moveType!= 0 && m == moves.size()-1){
            int[]tmp1 = new int[4];
            if(moveType==4){
                       int[] ret1 = getBestPromotion(board,figure,moves.get(m),isWhiteMove);
                       ret[0]=0;
                       ret[1]=0;
                       ret[2]=0;
                       ret[3]=0;
                        ret[4] = ret1[0];
                        ret[5] = ret1[1];
                        ret[6] = ret1[2];
                        ret[7] = ret1[3];
                    }
                    else{
                        if(m==moves.size()-1){
                            tmp1[0] = ret[4];
                            tmp1[1] = ret[5];
                            tmp1[2] = ret[6];
                            tmp1[3] = ret[7];
                            node.addMove(tmp1);
                        }
                    }


          }

          double note = alphaBeta(node,SEARCH_DEPTH,-INIT_NOTE,INIT_NOTE,isWhiteMove);
//          if(isWhiteMove)note=note*(-1);
            //if we are not running away from check then make this move less attractive
           ArrayList<int[]> singleMove =new ArrayList<int[]>();//for getting note only
           singleMove.add(tmp);
            double check = neural.isChecked(this.getActualBoard(singleMove), true);
          boolean accept = isMoveAccepted(check,isWhiteMove);
            if(!accept){
                note-=100;
            }
//        System.out.println("thread "+ID + " note: "+note +" bestNote: "+bestNote);
          if(note > bestNote){
//            if(note>bestNote){

//                //drugokowanie tablicy
//              char[][] tmpBoard = getActualBoard(node.getMoves());//zamien liste ruchow na plansze i zapisz board<=plansza
//              for(int row=0;row<tmpBoard.length;row++){
//                for(int c=0;c<tmpBoard[0].length;c++){
//                    System.out.print(""+tmpBoard[c][row]);
//                }
//                System.out.print("\n");
//               }
//              System.out.println("");
//              //koniec drukowania


//              for(int c = 0;c<=7; c++)
//                for(int r = 0;r<=7; r++)board[c][r]=tmpBoard[c][r];

               
                  finalMove[0]=new Point(tmp[0],tmp[1]);
                  finalMove[1]=new Point(tmp[2],tmp[3]);
                  bestNote=note;
                  root.removeChild(childNr-1);

                      finalAddMove[0] = moveType;
                     if(moveType!=0) System.arraycopy(ret,4, finalAddMove, 1, 4);

                  childNr--;
              
          }
          else{
              root.removeChild(childNr-1);
              childNr--;
          }
        }
    }
        synchronized(eng.addMoves){
            eng.addMoves[ID]=finalAddMove;
        }
        synchronized(eng.moves){
            eng.moves[ID]=finalMove;
            eng.threadFinish[ID]=true;
        }
        count1=count1+1;
    }
/**
 * True alpha - beta algorithm -it dynamically generates graph of possible moves
 * it is working in recurency
 * at the end we have note of each move - we chose the best move
 * @param node actual node
 * @param depth depth of the node
 * @param a note alpha
 * @param b note beta
 * @param maxPlayer if we look for max or min note
 * @return note of current node
 */
    public double alphaBeta(Node node,int depth,double a, double b,boolean maxPlayer) {
    char[][] tmpBoard = new char[8][8];

    boolean isWhiteP;
    if(maxPlayer)isWhiteP=this.isWhiteMove;
    else isWhiteP=!this.isWhiteMove;
    canCastles=castles;
//    canCastleB=castleB;
       for(int c = 0;c<=7; c++)
                for(int r = 0;r<=7; r++)tmpBoard[c][r]=getActualBoard(node.getMoves())[c][r];
    if (depth == 0) {
//        return calcNote(tmpBoard);
        double note = calcNote(tmpBoard);
        if(isWhiteMove)note=note*(-1);

//        System.out.println("isWhite: "+isWhiteMove + " note: "+note);
        return note;
    }

    ArrayList<Figures> myFigures = checkMyFigures(tmpBoard,isWhiteP,canCastles);

    if (maxPlayer){
        boolean stop = false;
        for(int f=0;f < myFigures.size() && !stop;f++){
            ArrayList<Point> moves = myFigures.get(f).checkPossibleMoves(tmpBoard);
            int tmpMoveType=0;
            int [] ret = new int[8];
             switch(myFigures.get(f).getType()){
                  case 'K':ret = checkForCastle(tmpBoard,isWhiteP);
//                           System.out.println("watek "+ID+" zwrocil "+ret + " dla bialych "+isWhiteMove);
                           if(ret!=null) {
                                moves.add(new Point(ret[2],ret[3]));
                                tmpMoveType=2;
                            }
                        break;
                 case 'P':ret = checkForJump(node,myFigures.get(f));
                             if(ret!=null) {
                                moves.add(new Point(ret[2],ret[3]));
                                tmpMoveType=3;
                                }
                if(moves.size()>0)
                 if(moves.get(0).y==0)tmpMoveType=4;

                        break;
                  default: tmpMoveType = 0;
                           for(int i=0;i<=7;i++)ret[i]=0;
                        break;
            }



            for(int m = 0;m<moves.size();m++){
                int[] addMove = new int[5];
                for(int i=0;i<5;i++)addMove[i]=0;
                if(tmpMoveType!=0 && m==moves.size()-1){
                    if(tmpMoveType==4){
                        ret = getBestPromotion(tmpBoard,myFigures.get(f),moves.get(m),isWhiteP);
                        addMove[0] = tmpMoveType;
                        addMove[1] = ret[0];
                        addMove[2] = ret[1];
                        addMove[3] = ret[2];
                        addMove[4] = ret[3];
                    }
                    else{
                        if(m==moves.size()-1){
                            addMove[0] = tmpMoveType;
                            addMove[1] = ret[4];
                            addMove[2] = ret[5];
                            addMove[3] = ret[6];
                            addMove[4] = ret[7];
                        }
                    }
                }
                a = Math.max(a, alphaBeta(createNode(node,myFigures.get(f).getPosX(),myFigures.get(f).getPosY(),moves.get(m),addMove)
                        ,depth-1,a,b,!maxPlayer));

                if (b<=a){
                    stop=true;

                    break;
                }
            }
        }
        return a;
    }
    // ####checking black player
    else {
        boolean stop = false;
        for(int f=0;f < myFigures.size() && !stop;f++){

            ArrayList<Point> moves = myFigures.get(f).checkPossibleMoves(tmpBoard);
            int tmpMoveType=0;
            int [] ret = new int[8];
             switch(myFigures.get(f).getType()){
                  case 'k':ret = checkForCastle(tmpBoard,isWhiteP);
                           if(ret!=null) {
                                moves.add(new Point(ret[2],ret[3]));
                                tmpMoveType=2;
                            }
                        break;
                  case 'p':ret = checkForJump(node,myFigures.get(f));
                             if(ret!=null) {
                                moves.add(new Point(ret[2],ret[3]));
                                tmpMoveType=3;
                                }
                          if(moves.size()>0)
                         if(moves.get(0).y==7)tmpMoveType=4;
                        break;

                  default: tmpMoveType = 0;
                           for(int i=0;i<=7;i++)ret[i]=0;
                        break;
            }

            for(int m = 0;m<moves.size();m++){
                int[] addMove = new int[5];
                for(int i=0;i<5;i++)addMove[i]=0;
                if(tmpMoveType!=0 && m==moves.size()-1){
                    if(tmpMoveType==4){
                        ret = getBestPromotion(tmpBoard,myFigures.get(f),moves.get(m),isWhiteP);
                        addMove[0] = tmpMoveType;
                        addMove[1] = ret[0];
                        addMove[2] = ret[1];
                        addMove[3] = ret[2];
                        addMove[4] = ret[3];
                    }
                    else{
                        if(m==moves.size()-1){
                            addMove[0] = tmpMoveType;
                            addMove[1] = ret[4];
                            addMove[2] = ret[5];
                            addMove[3] = ret[6];
                            addMove[4] = ret[7];
                        }
                    }
                }
                b = Math.min(b, alphaBeta(createNode(node,myFigures.get(f).getPosX(),myFigures.get(f).getPosY(),moves.get(m),addMove)
                        ,depth-1,a,b,!maxPlayer));
                if (b<=a){
                    stop=true;
                    break;
                }
            }
        }
        return b;
    }


 }
/**
 * method which creates node and automaticly add move to it's moves list
 * @param parent parent for current created node
 * @param posX new move from.x
 * @param posY new move from.y
 * @param destination new move to which figure is moved
 * @param additionalMove if additional move is needet to be done
 * @return created node
 */
    private Node createNode(Node parent,int posX,int posY, Point destination,int[] additionalMove) {
        Node child = new Node (parent);
        child.setParent(parent);
        parent.addChild(child);
        for(int m =0; m<parent.getMoves().size();m++){
            child.addMove(parent.getMoves().get(m));
        }
        int[] move = {posX,posY,destination.x,destination.y};//new int[4];
        child.addMove(move);
        if(additionalMove[0]!=0){
            int[] tmp = {additionalMove[1],additionalMove[2],additionalMove[3],additionalMove[4]};
            child.addMove(tmp);
        }
        count1++;
        return child;
    }
/**
 * method which search for available figures for player
 * @param board actual board
 * @param isWhiteMove which player is moving
 * @param canMakeCastles if castles can be made
 * @return list of figures
 */
private ArrayList<Figures> checkMyFigures(char[][] board,boolean isWhiteMove,boolean[] canMakeCastles) {

        ArrayList<Figures> myFigures = new ArrayList();

        if(isWhiteMove){                          //if its white's move we are looking for capital letters
            for(int c = 0;c<=7; c++)
                for(int r = 0;r<=7; r++){
                    switch(board[c][r]){
                        case 'N': myFigures.add(new Knight(true, new Point(c,r)));
                                        break;
                        case 'B': myFigures.add(new Bishop(true,new Point(c,r)));
                                        break;
                        case 'P': myFigures.add(new Pawn(true,new Point(c,r)));
                                        break;
                        case 'K': myFigures.add(new King(true,new Point(c,r),canMakeCastles[0],canMakeCastles[1]));
                                        break;
                        case 'R': myFigures.add(new Rouge(true,new Point(c,r)));
                                        break;
                        case 'Q': myFigures.add(new Queen(true,new Point(c,r)));
                                        break;
                    }
                }
        }
        else{
             for(int c = 0;c<=7; c++)
                for(int r = 0;r<=7; r++){
                    switch(board[c][r]){
                        case 'n': myFigures.add(new Knight(false, new Point(c,r)));
                                        break;
                        case 'b': myFigures.add(new Bishop(false,new Point(c,r)));
                                        break;
                        case 'p': myFigures.add(new Pawn(false,new Point(c,r)));
                                        break;
                        case 'k': myFigures.add(new King(false,new Point(c,r),canMakeCastles[2],canMakeCastles[3]));
                                        break;
                        case 'r': myFigures.add(new Rouge(false,new Point(c,r)));
                                        break;
                        case 'q': myFigures.add(new Queen(false,new Point(c,r)));
                                        break;
                    }
                }
        }
        return myFigures;
    }
/**
 * method whicz ask neural network what is the note of current board
 * @param board board to be rated
 * @return note of board
 */
 private double calcNote(char[][] board) {
        Random rand = new Random();
        int r  = rand.nextInt(100);

//        count2++;
//        System.out.println("ocena "+r);
//                      //drugokowanie tablicy
//              for(int row=0;row<board.length;row++){
//                for(int c=0;c<board[0].length;c++){
//                    System.out.print(""+board[c][row]);
//                }
//                System.out.print("\n");
//                }
//              System.out.println("");
//              //koniec drukowania

        double n = neural.getNote(board,isWhiteMove);
//        n=n+r;
        return n;

//        return r;

    }
/**
 * method which creates actual state of board given moves, which have to be made
 * @param moves list of moves
 * @return board after moves
 */
    public char[][] getActualBoard( ArrayList<int[]> moves) {
        char[][] board = new char[8][8];
        char[][] exBoard = {{'r','n','b','q','k','p','0'},
                            {'R','N','B','Q','K','P','0'}};
        for(int c = 0;c<=7; c++)
        for(int r = 0;r<=7; r++)board[c][r]=this.board[c][r];

        for(int m=0;m<moves.size();m++){
            if(moves.get(m)[1]<0){
                char figureType = exBoard[moves.get(m)[1]*(-1)-1][moves.get(m)[0]];
                 board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
                 continue;
            }
            else{
                   char figureType = board[moves.get(m)[0]][moves.get(m)[1]];
                if(figureType == 'K'){
                    canCastles[0]=false;
                    canCastles[1]=false;
                }
                if(figureType == 'k'){
                    canCastles[2]=false;
                    canCastles[3]=false;
                }
                if(figureType == 'r') {
                    if(moves.get(m)[0]==0) canCastles[2]=false;
                    else canCastles[3]=false;
                }
                  if(figureType == 'R') {
                    if(moves.get(m)[0]==0) canCastles[0]=false;
                    else canCastles[1]=false;
                }
                board[moves.get(m)[0]][moves.get(m)[1]]='0'; //we clear old location
                board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
            }
            
        }
        return board;
    }
    
 public char[][] getActualBoard( char[][] b,ArrayList<int[]> moves) {
        char[][] board = new char[8][8];
        char[][] exBoard = {{'r','n','b','q','k','p','0'},
                            {'R','N','B','Q','K','P','0'}};

        for(int c = 0;c<=7; c++)
        for(int r = 0;r<=7; r++)board[c][r]=b[c][r];

        for(int m=0;m<moves.size();m++){
            if(moves.get(m)[1]<0){
                char figureType = exBoard[moves.get(m)[1]*(-1)-1][moves.get(m)[0]];
                 board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
                 continue;
            }
            else{
                    char figureType = board[moves.get(m)[0]][moves.get(m)[1]];
                 if(figureType == 'K'){
                    canCastles[0]=false;
                    canCastles[1]=false;
                }
                if(figureType == 'k'){
                    canCastles[2]=false;
                    canCastles[3]=false;
                }
                if(figureType == 'r') {
                    if(moves.get(m)[0]==0) canCastles[2]=false;
                    else canCastles[3]=false;
                }
                  if(figureType == 'R') {
                    if(moves.get(m)[0]==0) canCastles[0]=false;
                    else canCastles[1]=false;
                }
                board[moves.get(m)[0]][moves.get(m)[1]]='0'; //we clear old location
                board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
            }
            
        }
        return board;
    }
/**
 * checking if king can make castle
 * @param tmpBoard actual board
 * @param maxPlayer if it is white or black players move
 * @return if castle can be made it retturn move for that castle
 */
    private int[] checkForCastle(char[][] tmpBoard, boolean maxPlayer) {
        if(maxPlayer){
            if(!canCastles[0] && !canCastles[1])
                return null;
        }
        else
            if(!canCastles[2] && !canCastles[3])
                return null;

        if(maxPlayer){
            double note1 = 0,note2=0;
            boolean shortCastle,longCastle;
            if(canCastles[1])
                shortCastle = checkShortCastle(tmpBoard,maxPlayer);
            else shortCastle=false;
          if(shortCastle){
              ArrayList<int[]> castleMoves= new ArrayList();
            int [] move = {7,7,5,7};
            castleMoves.add(move);
            move[0] = 4;
            move[1] = 7;
            move[2] = 6;
            move[3] = 7;
            castleMoves.add(move);
            note1 = calcNote(getActualBoard(tmpBoard,castleMoves));
          }
            if(canCastles[0])
                longCastle = checkLongCastle(tmpBoard,maxPlayer);
            else longCastle=false;
           if(longCastle){
               ArrayList<int[]> castleMoves= new ArrayList();
            int [] move = {0,7,3,7};
            castleMoves.add(move);
            move[0] = 4;
            move[1] = 7;
            move[2] = 2;
            move[3] = 7;
            castleMoves.add(move);
            note2 = calcNote(getActualBoard(tmpBoard,castleMoves));
           }
            if(shortCastle && longCastle){
                if(note1>note2){
                    int [] move = {4,7,6,7,7,7,5,7}; //king from,to; rook from,to
                    return move;
                }
                else {
                    int [] move = {4,7,2,7,0,7,3,7};//king from,to; rook from,to
                    return move;
                }
            }
            if(shortCastle && !longCastle){
                 int [] move = {4,7,6,7,7,7,5,7};
                    return move;
            }
            if(!shortCastle && longCastle){
                int [] move = {4,7,2,7,0,7,3,7};
                    return move;
            }
             return null;


        }
        //checking black player
        else{
            double note1 = 0,note2=0;
            boolean shortCastle,longCastle;
            if(canCastles[3])
                shortCastle = checkShortCastle(tmpBoard,maxPlayer);
            else shortCastle = false;
          if(shortCastle){
              ArrayList<int[]> castleMoves= new ArrayList();
            int [] move = {7,0,5,0};
            castleMoves.add(move);
            move[0] = 4;
            move[1] = 0;
            move[2] = 6;
            move[3] = 0;
            castleMoves.add(move);
            note1 = calcNote(getActualBoard(tmpBoard,castleMoves));
          }
            if(canCastles[2])
                longCastle = checkLongCastle(tmpBoard,maxPlayer);
            else longCastle = false;

           if(longCastle){
               ArrayList<int[]> castleMoves= new ArrayList();
            int [] move = {0,0,3,0};
            castleMoves.add(move);
            move[0] = 4;
            move[1] = 0;
            move[2] = 2;
            move[3] = 0;
            castleMoves.add(move);
            note2 = calcNote(getActualBoard(tmpBoard,castleMoves));
           }
            if(shortCastle && longCastle){
                if(note1>note2){
                    int [] move = {7,0,5,0,4,0,6,0};
                    return move;
                }
                else {
                    int [] move = {0,0,3,0,4,0,2,0};
                    return move;
                }
            }
            if(shortCastle && !longCastle){
                int [] move = {7,0,5,0,4,0,6,0};
                    return move;
            }
            if(!shortCastle && longCastle){
                int [] move = {0,0,3,0,4,0,2,0};
                    return move;
            }
             return null;

        }
    }

    private boolean checkShortCastle(char[][] tmpBoard, boolean maxPlayer) {
         if( tmpBoard[5][7]!='0' || tmpBoard[6][7]!='0') return false ;
            if(!checkIfSafe(tmpBoard,4,7,maxPlayer)) return false;
            if(!checkIfSafe(tmpBoard,5,7,maxPlayer)) return false;
            if(!checkIfSafe(tmpBoard,6,7,maxPlayer)) return false;
         return true;
    }

    private boolean checkLongCastle(char[][] tmpBoard, boolean maxPlayer) {
         if( tmpBoard[1][7]!='0' || tmpBoard[2][7]!='0'|| tmpBoard[3][7]!='0') return false ;
          if(!checkIfSafe(tmpBoard,2,7,maxPlayer)) return false;
            if(!checkIfSafe(tmpBoard,3,7,maxPlayer)) return false;
            if(!checkIfSafe(tmpBoard,4,7,maxPlayer)) return false;
         return true;
    }

      private boolean checkIfSafe(char[][] tmpBoard, int x, int y,boolean isWhite) {
        int n = 1 ;
        boolean s1= false,s2= false,s3= false,s4= false,s5= false;
        boolean s6= false,s7= false,s8= false;
        if(isWhite){
            while(n<=7){
                //W
                if(!s1){
                    if(x-n >=0){
                        if(tmpBoard[x-n][y]!='0'){
                            switch(tmpBoard[x-n][y]){
                                default:
                                    s1 = true;
                                            break;
                                case 'r': case 'q':
                                    System.out.println("blok W");
                                    return false;
                            }
                        }
                    }else s1=true;
                }
                //NW
                if(!s2){
                    if(x-n >=0 && y-n>=0){
                        if(tmpBoard[x-n][y-n]!='0'){
                            switch(tmpBoard[x-n][y-n]){
                                default:
                                         s2 = true;
                                            break;
                                case 'p': if(n==1) return false;
                                          else{
                                            s2=true;
                                            break;
                                        }
                                case 'b':
                                case 'q':
                                    System.out.println("blok NW");return false;

                            }
                        }
                    }else s2=true;
                }
                //N
                if(!s3){
                    if(y-n >=0){
                        if(tmpBoard[x][y-n]!='0'){
                            switch(tmpBoard[x][y-n]){
                                default:
                                    s3 = true;
                                            break;
                                case 'r':
                                case 'q':
                                    System.out.println("blok N");return false;

                            }
                        }
                    }else s3=true;
                }
                //NE
                if(!s4){
                    if(x+n <=7 && y-n>=0){
                        if(tmpBoard[x+n][y-n]!='0'){
                            switch(tmpBoard[x+n][y-n]){
                                default:
                                         s4 = true;
                                            break;
                                case 'p': if(n==1) return false;
                                          else{
                                            s4=true;
                                            break;
                                        }
                                case 'b':
                                case 'q':
                                    System.out.println("blok NE");return false;

                            }
                        }
                    }else s4=true;
                }
                //E
                if(!s5){
                    if(x+n <=7){
                        if(tmpBoard[x+n][y]!='0'){
                            switch(tmpBoard[x+n][y]){
                                default:
                                    s5 = true;
                                            break;
                                case 'r':
                                case 'q':
                                    System.out.println("blok E");return false;

                            }
                        }
                    }else s5=true;
                }
                //SW
                if(!s6){
                    if(x-n >=0 && y+n<=7){
                        if(tmpBoard[x-n][y+n]!='0'){
                            switch(tmpBoard[x-n][y+n]){
                                default:
                                         s6 = true;
                                            break;
                                case 'p': if(n==1) return false;
                                          else{
                                            s6=true;
                                            break;
                                        }
                                case 'b':
                                case 'q':
                                    System.out.println("blok SW");return false;

                            }
                        }
                    }else s6=true;
                }
                //S
                if(!s7){
                    if(y+n <=7){
                        if(tmpBoard[x][y+n]!='0'){
                            switch(tmpBoard[x][y+n]){
                                default:
                                    s7 = true;
                                            break;
                                case 'r':
                                case 'q':
                                    System.out.println("blok S");return false;

                            }
                        }
                    }else s7=true;
                }
                   //SE
                if(!s8){
                    if(x+n <=7 && y+n<=7){
                        if(tmpBoard[x+n][y+n]!='0'){
                            switch(tmpBoard[x+n][y+n]){
                                default:
                                         s8 = true;
                                            break;
                                case 'p': if(n==1) return false;
                                          else{
                                            s8=true;
                                            break;
                                        }
                                case 'b':
                                case 'q':
                                    System.out.println("blok SE");return false;

                            }
                        }
                    }else s8=true;
                }


                 n++;
            }
                //checking for oponents knight 0
                if(x-2>=0 && y-1>=0)
                    if(tmpBoard[x-2][y-1]=='n') return false;
                if(x-1>=0 && y-2>=0)
                    if(tmpBoard[x-1][y-2]=='n') return false;
                if(x+2<=7 && y-1>=0)
                    if(tmpBoard[x+2][y-1]=='n') return false;
                if(x+1<=7 && y-2>=0)
                    if(tmpBoard[x+1][y-2]=='n') return false;

                if(x-2>=0 && y+1<=7)
                    if(tmpBoard[x-2][y+1]=='n') return false;
                if(x-1>=0 && y+2<=7)
                    if(tmpBoard[x-1][y+2]=='n') return false;
                if(x+2<=7 && y+1<=7)
                    if(tmpBoard[x+2][y+1]=='n') return false;
                if(x+1<=7 && y+2<=7)
                    if(tmpBoard[x+1][y+2]=='n') return false;


        }

        //##################### checking black player ####################
        else{
            while(n<=7){
                //W
                if(!s1){
                    if(x-n >=0){
                        if(tmpBoard[x-n][y]!='0'){
                            switch(tmpBoard[x-n][y]){
                                default:
                                    s1 = true;
                                            break;
                                case 'R': case 'Q': return false;
                            }
                        }
                    }else s1=true;
                }
                //SW
                if(!s2){
                    if(x-n >=0 && y+n<=7){
                        if(tmpBoard[x-n][y+n]!='0'){
                            switch(tmpBoard[x-n][y+n]){
                                default:
                                         s2 = true;
                                            break;
                                case 'P': if(n==1) return false;
                                          else{
                                            s2=true;
                                            break;
                                        }
                                case 'B':
                                case 'Q': return false;

                            }
                        }
                    }else s2=true;
                }
                //S
                if(!s3){
                    if(y+n <=7){
                        if(tmpBoard[x][y+n]!='0'){
                            switch(tmpBoard[x][y+n]){
                                default:
                                    s3 = true;
                                            break;
                                case 'R':
                                case 'Q': return false;

                            }
                        }
                    }else s3=true;
                }
                //SE
                if(!s4){
                    if(x+n <=7 && y+n<=7){
                        if(tmpBoard[x+n][y+n]!='0'){
                            switch(tmpBoard[x+n][y+n]){
                                default:
                                         s4 = true;
                                            break;
                                case 'P': if(n==1) return false;
                                          else{
                                            s4=true;
                                            break;
                                        }
                                case 'B':
                                case 'Q': return false;

                            }
                        }
                    }else s4=true;
                }
                //E
                if(!s5){
                    if(x+n <=7){
                        if(tmpBoard[x+n][y]!='0'){
                            switch(tmpBoard[x+n][y]){
                                default:
                                    s5 = true;
                                            break;
                                case 'R':
                                case 'Q': return false;

                            }
                        }
                    }else s5=true;
                }
                //NW
                if(!s6){
                    if(x-n >=0 && y-n>=0){
                        if(tmpBoard[x-n][y-n]!='0'){
                            switch(tmpBoard[x-n][y-n]){
                                default:
                                         s6 = true;
                                            break;
                                case 'P': if(n==1) return false;
                                          else{
                                            s6=true;
                                            break;
                                        }
                                case 'B':
                                case 'Q': return false;

                            }
                        }
                    }else s6=true;
                }
                 //N
                if(!s7){
                    if(y-n >=0){
                        if(tmpBoard[x][y-n]!='0'){
                            switch(tmpBoard[x][y-n]){
                                default:
                                    s7 = true;
                                            break;
                                case 'R':
                                case 'Q': return false;

                            }
                        }
                    }else s7=true;
                }
                //NE
                if(!s8){
                    if(x+n <=7 && y-n>=0){
                        if(tmpBoard[x+n][y-n]!='0'){
                            switch(tmpBoard[x+n][y-n]){
                                default:
                                         s8 = true;
                                            break;
                                case 'P': if(n==1) return false;
                                          else{
                                            s8=true;
                                            break;
                                        }
                                case 'B':
                                case 'Q': return false;

                            }
                        }
                    }else s8=true;
                }



                n++;
            }
        //checking for oponents knight 0
                if(x-2>=0)
                    if(tmpBoard[x-2][y+1]=='N') return false;
                if(x-1>=0)
                    if(tmpBoard[x-1][y+2]=='N') return false;
                if(x+2<=7)
                    if(tmpBoard[x+2][y+1]=='N') return false;
                if(x+1<=7)
                    if(tmpBoard[x+1][y+2]=='N') return false;

                if(x-2>=0 && y+1<=7)
                    if(tmpBoard[x-2][y+1]=='N') return false;
                if(x-1>=0 && y+2<=7)
                    if(tmpBoard[x-1][y+2]=='N') return false;
                if(x+2<=7 && y+1<=7)
                    if(tmpBoard[x+2][y+1]=='N') return false;
                if(x+1<=7 && y+2<=7)
                    if(tmpBoard[x+1][y+2]=='N') return false;
       }
        if(s1 && s2 && s3 && s4 && s5 && s6 && s7 && s8 )return true;
        else return false;
    }

     /**
      * checking if pawn can make beat in passage
      * @param node node where we want to check for that move
      * @param figure object of pawn
      * @return if that move is possible it returns additional move to destroy oppontnts pawn
      */
    private int[] checkForJump(Node node, Figures figure) {
        boolean isWhite;
        if(node.getMoves().size()<=0) return null;
        if(figure.getType()>65 && figure.getType()<90) isWhite=true;
        else isWhite=false;
        char[][] tmpBoard= getActualBoard(node.getMoves());

        if(isWhite){
            double note1 = 0,note2=0;
            if((figure.getPosX()-1)>=0){
                if(tmpBoard[figure.getPosX()-1][figure.getPosY()]=='p'){
                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()-1,figure.getPosY()-2,figure.getPosX()-1,figure.getPosY()};
                    if(lastMove.equals(compare)) {


                        ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1}; //pawn from,to
                        jumpMoves.add(move);
                        move[0] = 6;        //zero from,to
                        move[1] = -1;
                        move[2] = figure.getPosX()-1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note1 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                }
            }
            if((figure.getPosX()+1)<=7){
                if(tmpBoard[figure.getPosX()+1][figure.getPosY()]=='p'){
                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()+1,figure.getPosY()-2,figure.getPosX()+1,figure.getPosY()};
                    if(lastMove.equals(compare)) {

                         ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()-1};
                        jumpMoves.add(move);
                        move[0] = 6;
                        move[1] = -1;
                        move[2] = figure.getPosX()+1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note2 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                }
            }
                 if(note1>note2){
                     int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1,    //pawn from,to
                        6,-1,figure.getPosX()-1,figure.getPosY()}; //zero from ,to
                     return ret;
                 }
                 else{
                    if(note2!=0){
                        int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()-1,    //pawn from,to
                        6,-1,figure.getPosX()+1,figure.getPosY()}; //zero from ,to
                        return ret;
                    }
                    else return null;
                 }


        }
        else{
            double note1 = 0,note2=0;
            if((figure.getPosX()-1)>=0){
                if(tmpBoard[figure.getPosX()-1][figure.getPosY()]=='P'){
                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()-1,figure.getPosY()+2,figure.getPosX()-1,figure.getPosY()};
                    if(lastMove.equals(compare)) {


                        ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()+1}; //pawn from,to
                        jumpMoves.add(move);
                        move[0] = 6;        //zero from,to
                        move[1] = -1;
                        move[2] = figure.getPosX()-1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note1 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                }
            }
            if((figure.getPosX()+1)<=7){
                if(tmpBoard[figure.getPosX()+1][figure.getPosY()]=='P'){
                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()+1,figure.getPosY()+2,figure.getPosX()+1,figure.getPosY()};
                    if(lastMove.equals(compare)) {

                         ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()+1};
                        jumpMoves.add(move);
                        move[0] = 6;
                        move[1] = -1;
                        move[2] = figure.getPosX()+1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note2 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                }
            }
                 if(note1>note2){
                     int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()+1,    //pawn from,to
                        6,-1,figure.getPosX()-1,figure.getPosY()}; //zero from ,to
                     return ret;
                 }
                 else{
                    if(note2!=0){
                        int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()+1,    //pawn from,to
                        6,-1,figure.getPosX()+1,figure.getPosY()}; //zero from ,to
                    return ret;
                    }
                    else return null;
                    
                 }
        }

    }

/**
 * checking what is the best option to promote pwan
 * @param tmpBoard actual board
 * @param figure object of pawn
 * @param destination what is the new location of pawn
 * @param isWhite if it is white player move
 * @return move which says to which figure change the pawn
 */
    private int[] getBestPromotion(char[][] tmpBoard, Figures figure, Point destination,boolean isWhite) {

        double finalNote = -INIT_NOTE;
        int[] fMove  = new int[4];
        int[] newMove  = new int[4];
        newMove[0]=figure.getPosX();
        newMove[1]=figure.getPosY();
        newMove[2]=destination.x;
        newMove[3]=destination.y;
        ArrayList<int[]> list = new ArrayList();
        list.add(newMove);
        for(int i=0;i<4;i++){
            newMove[0]=i;
            if(isWhite)
                newMove[1]=-2;
            else
                newMove[1]=-1;

            newMove[2]=destination.x;
            newMove[3]=destination.y;
            list.add(newMove);
            char[][] newBoard= getActualBoard(tmpBoard,list);
            double note = calcNote(newBoard);
            if(note>finalNote){
                finalNote=note;
                fMove[0]=newMove[0];
                fMove[1]=newMove[1];
                fMove[2]=newMove[2];
                fMove[3]=newMove[3];
            }
        }

        return fMove;
    }

    /**
      * checking if pawn can make beat in passage
      * @param node node where we want to check for that move
      * @param figure object of pawn
      * @return if that move is possible it returns additional move to destroy oppontnts pawn
      */
    private int[] checkForJump(Node node, Figures figure, Point[] lastMove) {
        boolean isWhite;
        if(figure.getType()>65 && figure.getType()<90) isWhite=true;
        else isWhite=false;
        char[][] tmpBoard= getActualBoard(node.getMoves());

        if(isWhite){
            double note1 = 0,note2=0;
            if((figure.getPosX()-1)>=0){
                if(tmpBoard[figure.getPosX()-1][figure.getPosY()]=='p'){
                    int[] compare = {figure.getPosX()-1,figure.getPosY()-2,figure.getPosX()-1,figure.getPosY()};
                    if(lastMove.equals(compare)) {


                        ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1}; //pawn from,to
                        jumpMoves.add(move);
                        move[0] = 6;        //zero from,to
                        move[1] = -1;
                        move[2] = figure.getPosX()-1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note1 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                        //{figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1};
                }
            }
            if((figure.getPosX()+1)<=7){
                if(tmpBoard[figure.getPosX()+1][figure.getPosY()]=='p'){
//                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()+1,figure.getPosY()-2,figure.getPosX()+1,figure.getPosY()};
                    if(lastMove.equals(compare)) {

                         ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()-1};
                        jumpMoves.add(move);
                        move[0] = 6;
                        move[1] = -1;
                        move[2] = figure.getPosX()+1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note2 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                        //{figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1};
                }
            }
                 if(note1>note2){
                     int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1,    //pawn from,to
                        6,-1,figure.getPosX()-1,figure.getPosY()}; //zero from ,to
                     return ret;
                 }
                 else{
                    if(note2!=0){
                        int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()-1,    //pawn from,to
                        6,-1,figure.getPosX()+1,figure.getPosY()}; //zero from ,to
                        return ret;
                    }
                    else return null;
                 }


        }
        else{
            double note1 = 0,note2=0;
            if((figure.getPosX()-1)>=0){
                if(tmpBoard[figure.getPosX()-1][figure.getPosY()]=='P'){
//                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()-1,figure.getPosY()+2,figure.getPosX()-1,figure.getPosY()};
                    if(lastMove.equals(compare)) {


                        ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()+1}; //pawn from,to
                        jumpMoves.add(move);
                        move[0] = 6;        //zero from,to
                        move[1] = -1;
                        move[2] = figure.getPosX()-1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note1 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                        //{figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1};
                }
            }
            if((figure.getPosX()+1)<=7){
                if(tmpBoard[figure.getPosX()+1][figure.getPosY()]=='P'){
//                    int[] lastMove = node.getMoves().get(node.getMoves().size()-1);
                    int[] compare = {figure.getPosX()+1,figure.getPosY()+2,figure.getPosX()+1,figure.getPosY()};
                    if(lastMove.equals(compare)) {

                         ArrayList<int[]> jumpMoves= new ArrayList();
                        int [] move = {figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()+1};
                        jumpMoves.add(move);
                        move[0] = 6;
                        move[1] = -1;
                        move[2] = figure.getPosX()+1;
                        move[3] = figure.getPosY();
                        jumpMoves.add(move);
                        note2 = calcNote(getActualBoard(tmpBoard,jumpMoves));
                    }
                        //{figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()-1};
                }
            }
                 if(note1>note2){
                     int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()-1,figure.getPosY()+1,    //pawn from,to
                        6,-1,figure.getPosX()-1,figure.getPosY()}; //zero from ,to
                     return ret;
                 }
                 else{
                    if(note2!=0){
                        int[] ret ={figure.getPosX(),figure.getPosY(),figure.getPosX()+1,figure.getPosY()+1,    //pawn from,to
                        6,-1,figure.getPosX()+1,figure.getPosY()}; //zero from ,to
                    return ret;
                    }
                    else return null;

                 }
        }
    }

    private boolean isChecked(char[][] board, Point[] finalMove, boolean whiteMove) {

         Neural neu = new Neural(true);

       char[][] tmpBoard = new char[8][8];
        for(int c = 0;c<=7; c++)
            for(int r = 0;r<=7; r++)tmpBoard[c][r]=board[c][r];
        char figureType = board[finalMove[0].x][finalMove[0].y];
        tmpBoard[finalMove[0].x][finalMove[1].y] = 0;
        tmpBoard[finalMove[1].x][finalMove[1].y]=figureType;

        int check = neu.isChecked(tmpBoard,false);

        if(whiteMove){
            if(check==-100 || check ==-1000) return true;
        }
        else{
            if(check==100 || check ==1000) return true;
        }

         return false;
    }

private boolean isMoveAccepted(double check, boolean whiteMove) {
        if(whiteMove){
        switch((int)check){
            case -100 : return false;
            case 100: return true;
            case -1000: return false;
            case 1000: return true;
            default:
                    break;
        }
        }
        else{
            switch((int)check){
                case -100 : return true;
                case 100: return false;
                case -1000: return true;
                case 1000: return false;
                default:
                        break;
            }
        }
        return true;
    }

     
}
